package net.imwork.amorgemini.core.utils.logback4mongo;

import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.status.ErrorStatus;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * Created by lvbr on 2017-09-06 20:01.
 */
public class MongoDBAppender extends AppenderBase<LoggingEvent> {

    private static final Logger logger = LoggerFactory.getLogger(MongoDBAppender.class);

    private MongoClient client;
    private String host = "127.0.0.1";
    private int port = 27017;
    private String dbName = "logging";
    private MongoCollection<Document> collection;

    @Override
    public void start() {
        try {
            client = new MongoClient(host, port);
            final MongoDatabase db = client.getDatabase(dbName);
            collection = db.getCollection(super.getName());
        } catch (Exception e) {
            addStatus(new ErrorStatus("Failed to initialize MondoDB", this, e));
            return;
        }
        super.start();
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setDbName(String dbName) {
        this.dbName = dbName;
    }

    @Override
    public void stop() {
        client.close();
        super.stop();
    }

    @Override
    protected void append(LoggingEvent e) {
        Map<String, String> mdc = e.getMDCPropertyMap();
        Document log = new Document()
                .append("ts", e.getTimeStamp())
                .append("level", e.getLevel().toString())
                .append("msg", e.getFormattedMessage())
                .append("logger", e.getLoggerName())
                .append("thread", e.getThreadName());
        if (e.hasCallerData()) {
            StackTraceElement st = e.getCallerData()[0];
            String callerData = String.format("%s.%s:%d", st.getClassName(), st.getMethodName(), st.getLineNumber());
            log.append("caller", callerData);
        }
        if (mdc != null && !mdc.isEmpty()) {
            log.append("mdc", new BasicDBObject(mdc));
        }
        collection.insertOne(log);
    }
}
